
#include"projectHeader.h"

void processStoreCmd()
{
//	printf("Inside store function call.\n");

	/*list<string> ::iterator it;
	printf("Values are:\n");
	for(it=storeKeywordsList.begin();it!=storeKeywordsList.end();it++)
	{
		printf("%s\n",(char*)(*it));
		//storeKeywordsList.pop_front();
	}
	*/

	//======================
	//Calcute the file size.
	//======================
	struct stat statistics;
	int status;
	
	status = stat((char*)storeFileName,&statistics);
	if(status<0)
	{
		printf("File does not exist.\n");
		return;
	}
	unsigned int filesize = statistics.st_size;

//	printf("Size of file %s is %u.\n",storeFileName,filesize);
	
	//============================================================================
	//Calculate the SHA1 for entire file. This will be the SHA1 value of the file.
	//============================================================================
	
	char sha1buf[MAXFILEBUF+1];
	
	SHA_CTX c;
	SHA1_Init(&c);

	FILE *storeFile = fopen(storeFileName, "r");
	//filesize=65535;
	int numberOfSegments = ceil((double)filesize/MAXFILEBUF);	
//	printf("Number of Segments is %d\n",numberOfSegments);
	int dataleft=filesize;
	for(int k=0;k<numberOfSegments;k++)
	{
		int bytestoread;
		if (dataleft > MAXFILEBUF)
		{
			bytestoread = MAXFILEBUF;
			dataleft = dataleft - MAXFILEBUF;
		}
		else
			bytestoread = dataleft;

		memset(sha1buf,'\0', MAXFILEBUF+1);
		if (fread(sha1buf,1,bytestoread,storeFile) < 0)
		{
			printf("Error in reading store file\n");
		}
		SHA1_Update(&c,(void *)sha1buf,bytestoread);
	}

	fclose(storeFile);
	unsigned char sha1StoreFile[20];
	SHA1_Final(sha1StoreFile,&c);
	
	//	printf("Calculated SHA1: ");
	/*	for(unsigned int i=0; i<20;i++)
		{
			printf("%x",sha1StoreFile[i]);
		}
		printf("\n");
*/

	//=====================================================================
	//calculate the bitvector of all the keywords associated with the file
	//=====================================================================
	
	unsigned char storeFileBitVector[128];
	memset(&storeFileBitVector[0],0x00,128);

/*	printf("Bit Vector is:\n\n");
	for(int k=127;k>=0;k--)
	{
		printf("%x",storeFileBitVector[k]);
	}
	printf("\n");*/
	calcBitVector(storeFileBitVector);
/*	printf("Final Bit Vector is:\n\n");
	for(int k=127;k>=0;k--)
	{
		printf("%x",storeFileBitVector[k]);
	}
	printf("\n");
*/
	
	//======================================================
	//genarate the random password and calculate the nounce
	//======================================================

	char randFilePassword[21];
	memset(&randFilePassword[0],'\0',21);
	for(int k=0;k<20;k++)
	{
		generateRandChar(&randFilePassword[k]);
	
	}
	randFilePassword[20]='\0';
//	printf("\n\nPassword generated is %s\n",randFilePassword);
	
	//caclulate sha1 of random password to generate nounce

	unsigned char storeFileNonce[20];
	memset(&storeFileNonce[0],'\0',20);
	
	//char *s ="adfsdadfsdadfsdadfsd";
	SHA1((unsigned char*)randFilePassword, 20, storeFileNonce);
	//SHA1((unsigned char*)s, 20, storeFileNonce);
//	printf("Nonce is:\n\n");
/*	for(int k=0;k<20;k++)
	{
		printf("%x",storeFileNonce[k]);
	}
	printf("\n");
*/	
		
// Change to file writeable format.
	
	char formattedFileSha1[41];
	memset(&formattedFileSha1[0],'\0',41);
	for (int i =0 ;i< 20 ;i++)
	{
		unsigned char change[3] = {0};
		sprintf((char*)change, "%2.2x", sha1StoreFile[i]);
		sprintf((char*)formattedFileSha1+2*i,"%s",change);
	}

	char formattedNonce[41];
	memset(&formattedNonce[0],'\0',41);
	for (int i =0 ;i< 20 ;i++)
	{
		unsigned char change[3] = {0};
		sprintf((char*)change, "%2.2x", storeFileNonce[i]);
		sprintf((char*)formattedNonce+2*i,"%s",change);
	}

	char formattedBitVector[257];
	memset(&formattedBitVector[0],'\0',257);
	for (int i =0 ;i< 128 ;i++)
	{
		unsigned char change[3] = {0};
		sprintf((char*)change, "%2.2x", storeFileBitVector[i]);
		sprintf((char*)formattedBitVector+2*i,"%s",change);
	}
/// Update the indexing data structures for this file.
// Generate the File Id
	   char fileID[21];
	  unsigned char *buff1;
	char* msg = (char*)"file";
	memset(fileID,'\0',21);
	//printf("NodeID is %s\n",nodeInstanceId);
	
	buff1=GetUOID((char *)nodeInstanceId,msg,buf, sizeof(buf));
	memcpy(&fileID[0],&buf[0],20);
//	printf("FILE ID is %d\n",strlen(fileID));
//	printUOID((unsigned char*)fileID);
	//printUOID(buff1);
	pthread_mutex_lock(&indexMutex);
	// Update all index structures.
	
	char appendDFileName[256];
	char appendMFileName[256];
	memset(&appendMFileName[0],'\0',256);
	memset(&appendDFileName[0],'\0',256);

	int numfileId=numFileNameCounter++;

	sprintf(appendDFileName, "/%d.data", numfileId);
	sprintf(appendMFileName, "/%d.meta", numfileId);

	

	// populate bitvector index list
	bitVectorIndexItem indexBVItem;
	memcpy(&indexBVItem.indexBitVector[0],&formattedBitVector[0],256);
	indexBVItem.numFileName=numfileId;
	indexBitVectoreList.push_back(indexBVItem);
	
	//populate SHA1 vs numeric name map
	indexSHA1Map.insert(pair<string,int>(string(formattedFileSha1),numfileId));
	// populate the numeric name vs fildId map
//	printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
//	printf("File ID is:\n");
//	printUOID((unsigned char *)fileID);
	numToFileIdMap.insert(pair<int,string>(numfileId,string(fileID)));


	// populate the meta info list.

	indexFileMetaInfo fileMetaInfo;
	memset(&fileMetaInfo.originalFileName[0],'\0',256);
	memcpy(&fileMetaInfo.originalFileName[0],&storeFileName[0],strlen(storeFileName));
	fileMetaInfo.numFileName=numfileId;
	
	memcpy(&fileMetaInfo.fileID[0],&fileID[0],20);
	fileMetaInfo.filesize=filesize;
	fileMetaInfo.isInCache=false;
	memcpy(&fileMetaInfo.filePassword[0],&randFilePassword[0],20);
	memcpy(&fileMetaInfo.fileNonceValue[0],&formattedNonce[0],40);
	
	indexFileMetaInfoList.push_back(fileMetaInfo);

	pthread_mutex_unlock(&indexMutex);


// Write the data gathered to .meta file

	char newNumDataFile[256];
	char newNumMetaFile[256];
	memset(newNumDataFile, '\0', 256);
	memset(newNumMetaFile, '\0', 256);
	
	memcpy(newNumDataFile,homeDir,strlen(homeDir));
	strcat(newNumDataFile,"/files");
	
	//http://www.linuxquestions.org/questions/programming-9/mkdir-in-c-setting-wrong-permissions-613250/
	
	mkdir(newNumDataFile,S_IRWXU | S_IRWXG | S_IRWXO);
	strcat(newNumDataFile,appendDFileName); //Change it to variable numebr file generated in indexing above
	

	memcpy(newNumMetaFile,homeDir,strlen(homeDir));
	strcat(newNumMetaFile,"/files");
	
	//http://www.linuxquestions.org/questions/programming-9/mkdir-in-c-setting-wrong-permissions-613250/
	
	mkdir(newNumMetaFile,S_IRWXU | S_IRWXG | S_IRWXO);
	strcat(newNumMetaFile,appendMFileName); //Change it to variable numebr file generated in indexing above

	
//	printf("Data File Path is: %s\n",newNumDataFile);
//	printf("Meta File Path is: %s\n",newNumMetaFile);
	

	//copy data into numericData file.
	FILE *numDataFile = fopen(newNumDataFile, "w");
	FILE *sfile = fopen(storeFileName, "r");

	int remainingDataToBeCopied = filesize;
	 char copyBuf[MAXFILEBUF];
	 memset(&copyBuf[0],'\0',MAXFILEBUF);
	for(int k=0;k<numberOfSegments;k++)
	{
		int bytestoread;
		if (remainingDataToBeCopied > MAXFILEBUF)
		{
			bytestoread = MAXFILEBUF;
			remainingDataToBeCopied = remainingDataToBeCopied - MAXFILEBUF;
		}
		else
			bytestoread = remainingDataToBeCopied;

		memset(&copyBuf[0],'\0',MAXFILEBUF);
		if (fread(copyBuf,1,bytestoread,sfile) < 0)
		{
			printf("Error in reading store file\n");
		}
		fwrite(copyBuf, 1, bytestoread, numDataFile);	
	}
	fclose(numDataFile);
	fclose(sfile);

//	printf("Numeric File Written.\n");
	

	// Write the numeric meta file.

	FILE *numMetaFile = fopen(newNumMetaFile, "w");
	//----------
	memset(copyBuf, '\0', MAXFILEBUF);
	sprintf(copyBuf, "[metadata]\n");
	fwrite(copyBuf,1,strlen(copyBuf),numMetaFile);
	//----------
	memset(copyBuf, '\0', MAXFILEBUF);
	sprintf(copyBuf, "FileName=%s\n", storeFileName);
	fwrite(copyBuf,1,strlen(copyBuf),numMetaFile);
	//----------
	memset(copyBuf, '\0', MAXFILEBUF);
	sprintf(copyBuf, "FileSize=%u\n", filesize);
	fwrite(copyBuf,1,strlen(copyBuf),numMetaFile);
	//----------
	
	

	memset(copyBuf, '\0', MAXFILEBUF);
	sprintf(copyBuf, "SHA1=");
	memcpy(copyBuf+5, formattedFileSha1, 40);
	memcpy(copyBuf+45, "\n", 1);
	fwrite(copyBuf,1,46,numMetaFile);
	
	//-------------
	memset(copyBuf, '\0', MAXFILEBUF);
	sprintf(copyBuf, "Nounce=");
	memcpy(copyBuf+7, formattedNonce, 40);
	memcpy(copyBuf+47, "\n", 1);
	fwrite(copyBuf,1,48,numMetaFile);
	//------------------------
	memset(copyBuf, '\0', MAXFILEBUF);

	list<string> ::iterator it2;
	sprintf(copyBuf, "Keywords=");
	int writeKeywordPosition = 9;
	for(it2=storeKeywordsList.begin();it2!=storeKeywordsList.end();it2++)
	{
//		printf("Keyword is %s,\n",(*it2).c_str());
		sprintf(copyBuf+writeKeywordPosition,"%s ",(*it2).c_str());
		writeKeywordPosition = writeKeywordPosition+ strlen((*it2).c_str())+1;
	}
	memcpy(copyBuf+writeKeywordPosition-1, "\n", 1);
	fwrite(copyBuf,1,writeKeywordPosition,numMetaFile);
	
	memset(copyBuf, '\0', MAXFILEBUF);
	sprintf(copyBuf, "Bit-vector=");
	memcpy(copyBuf+11,formattedBitVector,256);
	memcpy(copyBuf+11+256, "\n",1);
	fwrite(copyBuf,1,256+11,numMetaFile);

	fclose(numMetaFile);

	// Populate the Packet and Broadcast according to probabilty to neighbours.

	

	msgHeaderClass storeMsgHeader;


	storeMsgHeader.messageType=0xCC;
	unsigned char *buff2;
	char* msg1 = (char*)"STOR";	
	buff2=GetUOID((char *)nodeInstanceId,msg1,buf, sizeof(buf));
	memcpy(storeMsgHeader.UOID,buf,20);
	storeMsgHeader.ttlInHeader=storeInputTTL;

	struct stat statistics1;
	int status1;
	status1 = stat((char*)newNumMetaFile,&statistics1);
	if(status1<0)
	{
		printf("File does not exist.\n");
	}
	unsigned int metaFileSize = statistics1.st_size;
//	printf("Size of file %s is %u.\n",newNumMetaFile,metaFileSize);


	storeMsgHeader.msgDataLength= metaFileSize + filesize +4;
	

		/*float coinflip = drand48();
		printf("CoinFlip %f NeighbourProb %f\n",coinflip,neighbourStoreProb);
			if (coinflip > neighbourStoreProb)
			{
				//continue; //we do not flood this message.
			}
		*/
						pthread_mutex_lock(&UOIDMsgLifeTimeMapMutex);
						unsigned char uoidToInsertInMap[20];
						memcpy(&uoidToInsertInMap[0],storeMsgHeader.UOID,20);
						string uoid((const char*)uoidToInsertInMap,20);
						msgLifeTimeClass newEntry(-1,msgLifeTime);
						//newEntry.sockOfMsgReciept=itemFromQueue.sockfd;
						//newEntry.msgLifeTimeValue=msgLifeTime;
						UOIDMsgLifeTimeMap.insert(pair<string,msgLifeTimeClass>(uoid,newEntry));

						pthread_mutex_unlock(&UOIDMsgLifeTimeMapMutex);

	queueItem writeQueueItem;
	map<string,int>::iterator conNodeListIterator;
	for ( conNodeListIterator=connectedNodeList.begin() ; conNodeListIterator != connectedNodeList.end(); conNodeListIterator++ )
	{
			float coinflip = drand48();
//			printf("CoinFlip %f NeighbourProb %f\n",coinflip,neighbourStoreProb);
			if (coinflip > neighbourStoreProb)
			{
				continue; //we do not flood this message.
			}


			// create queue item packet
			memset(&writeQueueItem,0,sizeof(queueItem));
			writeQueueItem.msgHeader = storeMsgHeader;
			//char c = '\0';
			//sprintf()
			//memcpy(&writeQueueItem.dataBuf[0],appendMFileName,strlen(appendMFileName));
			writeQueueItem.dataBuf[0] = (char)numfileId;
			writeQueueItem.dataBuf[1] = (char)' ';
			writeQueueItem.dataBuf[2] = (char)'0';
			//writeQueueItem.dataBuf[1] = count;			/*This is for counting semaphore. Here give index to the write thread which will be decremented there.*/
			//writeQueueItem.sockfd=-1;
			//writeQueueItem.msgHeader.messageType=0xF6;
//			printf("---------Queueitem header is :\n");
/*			printf("r STRS %d 0x%02x %x%x%x%x %x\n",
							(writeQueueItem.msgHeader.msgDataLength+27),
							(unsigned char)writeQueueItem.msgHeader.ttlInHeader,
							(unsigned char)writeQueueItem.msgHeader.UOID[16],
							(unsigned char)writeQueueItem.msgHeader.UOID[17],
							(unsigned char)writeQueueItem.msgHeader.UOID[18],
							(unsigned char)writeQueueItem.msgHeader.UOID[19],
							(unsigned char)writeQueueItem.dataBuf[0]);
*/
			// write into the appropriate write index
				//uint16_t portTemp=0;
				//char *tempHost=(char*)malloc(512);
					//printf("---------------5--------------\n");
					int socket=(*conNodeListIterator).second;
//					printf("---------------5--------------%d\n",socket);
						//printf("---------------6--------------\n");
						pthread_mutex_lock(&sockIndexMapMutex);
						int index=sockFDToQIndexMap[socket];
							pthread_mutex_lock(&wrtieQMutex[index]);
	//							printf("STORE PROCESS THREAD: Will push %s data in queue.\n\n",writeQueueItem.dataBuf);
								wrtieThreadQueue[index].push_back(writeQueueItem);
	//							printf("STORE PROCESS THREAD: STORE MSG: Msg pushed to writeQueue of %d\n",index);
								pthread_cond_broadcast(&wrtieQCV[index]);

							pthread_mutex_unlock(&wrtieQMutex[index]);								
						pthread_mutex_unlock(&sockIndexMapMutex);

				

	}
/*	int x = 20;
	while(x--)
	{
		sleep(1);
	}
	*/


	return;
}
